package redora.client.upgrade;

import java.util.Iterator;
import java.util.Set;

import redora.configuration.rdo.gwt.constants.Constants;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.gen2.table.client.FixedWidthFlexTable;
import com.google.gwt.gen2.table.client.FixedWidthGrid;
import com.google.gwt.gen2.table.client.ScrollTable;
import com.google.gwt.gen2.table.client.SelectionGrid.SelectionPolicy;
import com.google.gwt.gen2.table.override.client.FlexTable.FlexCellFormatter;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.LazyPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTML;

public class RedoraConfigurationViewPanel extends LazyPanel {

    final String baseUpgradeUrl = "../redoraOperations.do?";

    private ScrollTable scrollTable = null;

    Constants constants = GWT.create(Constants.class);

    FlowPanel root = new FlowPanel();

    public RedoraConfigurationViewPanel() {

    }

    protected Widget createWidget() {
        FlowPanel root = new FlowPanel();
        // Combine the components into a ScrollTable
        final ScrollTable scrollTable = createScrollTable();

        createDataList();

        final HTML label = new HTML();

        VerticalPanel panel = new VerticalPanel();

        panel.setWidth("100%");

        FlexTable table = new FlexTable();
        // table.setWidth("500");

        HTML upgrade = new HTML("<a href=javascript:void(0)>Upgrade</a>");
        upgrade.addClickHandler(new ClickHandler() {
            String url = URL.encode(baseUpgradeUrl + "_operationType=upgradeObjectTable");
            RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

            public void onClick(ClickEvent arg0) {
                builder.setCallback(new RequestCallback() {
                    public void onError(Request request, Throwable exception) {
                        Window.alert("Upgrade Table failed!");
                    }

                    public void onResponseReceived(Request request, Response response) {
                        label.setHTML(response.getText());
                        scrollTable.getDataTable().clearAll();
                        createDataList();
                    }
                });
                try {
                    builder.send();
                } catch (RequestException e) {
                    e.printStackTrace();
                }
            }

        });

        HTML check = new HTML("<a href=javascript:void(0)>Check</a>");
        check.addClickHandler(new ClickHandler() {

            String url = URL.encode(baseUpgradeUrl + "_operationType=checkObjectField");
            RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

            public void onClick(ClickEvent arg0) {
                builder.setCallback(new RequestCallback() {
                    public void onError(Request request, Throwable exception) {
                        Window.alert("Check Object Fields failed!");
                    }

                    public void onResponseReceived(Request request, Response response) {
                        label.setHTML(response.getText());
                    }
                });
                try {
                    builder.send();
                } catch (RequestException e) {
                    e.printStackTrace();
                }
            }
        });

        HTML dropAll = new HTML("<a href=javascript:void(0)>Drop All Tables</a>");
        dropAll.addClickHandler(new ClickHandler() {

            String url = URL.encode(baseUpgradeUrl + "_operationType=dropAllTables");
            RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

            public void onClick(ClickEvent arg0) {
                if (!Window.confirm("Are you sure?"))
                    return;
                builder.setCallback(new RequestCallback() {
                    public void onError(Request request, Throwable exception) {
                        Window.alert("Drop All Tables failed!");
                    }

                    public void onResponseReceived(Request request, Response response) {
                        Window.alert("All tables are dropped!");
                        scrollTable.getDataTable().clearAll();
                        scrollTable.getDataTable().resizeRows(0);
                    }
                });
                try {
                    builder.send();
                } catch (RequestException e) {
                    e.printStackTrace();
                }
            }
        });

        table.setWidget(0, 0, upgrade);
        table.setWidget(0, 1, check);
        table.setWidget(0, 2, dropAll);

        panel.add(table);
        
        final HTML drop = new HTML("<a href=javascript:void(0)>Drop</a>");

        final ListBox objectBox = new ListBox();
        String url = URL.encode(baseUpgradeUrl + "_operationType=getObjectNames");
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
        builder.setCallback(new RequestCallback() {
            public void onError(Request request, Throwable exception) {
                Window.alert("Upgrade Table failed!");
            }

            public void onResponseReceived(Request request, Response response) {
                JSONArray array = JSONParser.parse(response.getText()).isArray();
                for (int i = 0; i < array.size(); i++) {
                    objectBox.addItem(array.get(i).isObject().get("objectName").isString()
                            .stringValue(), array.get(i).isObject().get("objectName").isString()
                            .stringValue());
                }
                drop.addClickHandler(new ClickHandler() {
                    final String objectName = objectBox.getItemText(objectBox.getSelectedIndex());
                    String url = URL.encode(baseUpgradeUrl + "_operationType=dropTable&objectName="
                            + objectName);
                    RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

                    public void onClick(ClickEvent arg0) {
                        if (!Window.confirm("Are you sure?"))
                            return;
                        builder.setCallback(new RequestCallback() {
                            public void onError(Request request, Throwable exception) {
                                Window.alert("Drop " + objectName + " failed!");
                            }

                            public void onResponseReceived(Request request, Response response) {
                                Window.alert("Table " + objectName + " are dropped!");
                            }
                        });
                        try {
                            builder.send();
                        } catch (RequestException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
        try {
            builder.send();
        } catch (RequestException e) {
            e.printStackTrace();
        }
        
        FlexTable dropTable = new FlexTable();
        dropTable.setWidget(0, 0, new Label("Select a object table to drop :"));
        dropTable.setWidget(0, 1, objectBox);
        dropTable.setWidget(0, 2, drop);

        panel.add(dropTable);

        panel.add(label);
        // Add the components to the page
        root.add(scrollTable);
        root.add(panel);
        return root;
    }

    /**
     * Create the scroll table.
     * 
     * @return a data table
     */
    private ScrollTable createScrollTable() {
        FixedWidthFlexTable headerTable = createHeaderTable();
        FixedWidthFlexTable footerTable = createFooterTable();
        FixedWidthGrid dataTable = createDataTable();

        // Combine the components into a ScrollTable
        scrollTable = new ScrollTable(dataTable, headerTable);
        scrollTable.setFooterTable(footerTable);

        // Set some options in the scroll table
        // scrollTable.setSortingEnabled(true);
        scrollTable.setResizePolicy(ScrollTable.ResizePolicy.FILL_WIDTH);
        scrollTable.setSize("100%", "500");

        // Setup some default widths
        scrollTable.setColumnWidth(2, 50);
        scrollTable.setColumnWidth(5, 50);

        // Return the data table
        return scrollTable;
    }

    /**
     * Create the data table.
     * 
     * @return a data table
     */
    private FixedWidthGrid createDataTable() {
        // Create a new table
        FixedWidthGrid dataTable = new FixedWidthGrid();

        // dataTable.setSelectionPolicy(SelectionGrid.SelectionPolicy.MULTI_ROW);

        dataTable.setSelectionPolicy(SelectionPolicy.CHECKBOX);

        dataTable.resizeColumns(6);

        // Return the data table
        return dataTable;
    }

    /**
     * Get the User Data List.
     * 
     */
    private void createDataList() {
        final FixedWidthGrid dataTable = scrollTable.getDataTable();
        String url = URL.encode(baseUpgradeUrl + "_operationType=fetchRedoraScript");
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
        builder.setCallback(new RequestCallback() {
            public void onError(Request request, Throwable exception) {
                Window.alert("Page script failed!");
            }

            public void onResponseReceived(Request request, Response response) {
                JSONObject object = JSONParser.parse(response.getText()).isObject();
                JSONArray jsons = object.get("response").isObject().get("data").isArray();
                copyValue(dataTable, jsons);
            }
        });
        try {
            builder.send();
        } catch (RequestException e) {
            e.printStackTrace();
        }
    }

    /**
     * Create the footer table.
     * 
     * @return a footer table
     */
    private FixedWidthFlexTable createFooterTable() {
        // Create a new table
        FixedWidthFlexTable footerTable = new FixedWidthFlexTable();
        // FlexCellFormatter formatter = footerTable.getFlexCellFormatter();
        // Return the footer table
        return footerTable;
    }

    /**
     * Create the header table.
     * 
     * @return a header table
     */
    private FixedWidthFlexTable createHeaderTable() {
        // Create a new table
        FixedWidthFlexTable headerTable = new FixedWidthFlexTable();
        FlexCellFormatter formatter = headerTable.getFlexCellFormatter();

        // Level 1 headers
        // headerTable.setHTML(0, 0, "<b>User Data</b>");
        // formatter.setColSpan(0, 0, 9);
        // formatter.setHorizontalAlignment(0, 0,
        // HasHorizontalAlignment.ALIGN_CENTER);

        final CheckBox selectAll = new CheckBox();
        selectAll.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent arg0) {
                if (selectAll.getValue()) {
                    scrollTable.getDataTable().selectAllRows();
                } else {
                    scrollTable.getDataTable().deselectAllRows();
                }
            }

        });
        headerTable.setWidget(0, 0, selectAll);
        formatter.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
        headerTable.setHTML(0, 1, "Id");
        formatter.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
        headerTable.setHTML(0, 2, constants.redoraConfiguration_scriptName_table());
        formatter.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER);
        headerTable.setHTML(0, 3, constants.redoraConfiguration_status_table());
        formatter.setHorizontalAlignment(1, 3, HasHorizontalAlignment.ALIGN_CENTER);
        headerTable.setHTML(0, 4, "output");
        formatter.setHorizontalAlignment(1, 4, HasHorizontalAlignment.ALIGN_CENTER);
        headerTable.setHTML(0, 5, "creationDate");
        formatter.setHorizontalAlignment(1, 5, HasHorizontalAlignment.ALIGN_CENTER);
        headerTable.setHTML(0, 6, "updateDate");
        formatter.setHorizontalAlignment(1, 6, HasHorizontalAlignment.ALIGN_CENTER);

        // Return the header table
        return headerTable;
    }

    private void copyValue(FixedWidthGrid dataTable, JSONArray array) {
        dataTable.resizeRows(array.size());
        for (int i = 0; i < array.size(); i++) {
            JSONObject value = array.get(i).isObject();
            if (value.get("id") != null && !value.get("id").toString().equalsIgnoreCase("null")) {
                dataTable.setText(i, 0, value.get("id").toString());
            }
            if (value.get("scriptName") != null
                    && !value.get("scriptName").toString().equalsIgnoreCase("null")) {
                final int row = i;
                HTML link = new HTML("<a href=javascript:void(0)>"
                        + value.get("scriptName").isString().stringValue() + "</a>");
                dataTable.setWidget(i, 1, link);
                link.addClickHandler(new ClickHandler() {

                    public void onClick(ClickEvent arg0) {
                        scrollTable.getDataTable().selectRow(row, true);
                        PopupPanel popupPanel = createPopupPanel();
                        popupPanel.setGlassEnabled(true);
                        popupPanel.setAnimationEnabled(true);
                        popupPanel.center();
                        popupPanel.show();
                    }

                });
            }
            if (value.get("status") != null
                    && !value.get("status").toString().equalsIgnoreCase("null")) {
                dataTable.setText(i, 2, value.get("status").isString().stringValue());
                if (value.get("status").isString().stringValue().equalsIgnoreCase("Error")) {
                    final int row = i;
                    HTML link = new HTML("<a href=javascript:void(0)>Show Errors Details</a>");
                    dataTable.setWidget(i, 3, link);
                    final String _url = URL.encode(baseUpgradeUrl
                            + "_operationType=getScriptOutput&id="
                            + scrollTable.getDataTable().getText(i, 0));

                    link.addClickHandler(new ClickHandler() {
                        public void onClick(ClickEvent arg0) {
                            scrollTable.getDataTable().selectRow(row, true);
                            final PopupPanel popupPanel = new PopupPanel();
                            popupPanel.setStyleName("redora-popups-Popup");
                            HTML msg = new HTML("<center><b>Script Error Output</b></center>",
                                    false);
                            popupPanel.setGlassEnabled(true);
                            popupPanel.setAnimationEnabled(true);
                            final HTML label = new HTML();
                            RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, _url);
                            builder.setCallback(new RequestCallback() {
                                public void onError(Request request, Throwable exception) {
                                    Window.alert("fetch RedoraConfiguration output field failed!");
                                }

                                public void onResponseReceived(Request request, Response response) {
                                    JSONObject object = JSONParser.parse(response.getText())
                                            .isObject();
                                    JSONObject json = object.get("response").isObject().get("data")
                                            .isObject();
                                    if (json.get("output") != null
                                            && !json.get("output").toString().equalsIgnoreCase(
                                                    "null"))
                                        label.setHTML(json.get("output").isString().stringValue());
                                }
                            });
                            try {
                                builder.send();
                            } catch (RequestException e) {
                                e.printStackTrace();
                            }
                            VerticalPanel dialogContents = new VerticalPanel();
                            dialogContents.add(msg);
                            dialogContents.add(label);
                            // Add a close button at the bottom of the dialog
                            Button closeButton = new Button("close", new ClickHandler() {
                                public void onClick(ClickEvent event) {
                                    popupPanel.hide();
                                }
                            });
                            dialogContents.add(closeButton);
                            popupPanel.add(dialogContents);
                            popupPanel.center();
                            popupPanel.show();
                        }

                    });
                } else
                    dataTable.setText(i, 3, null);
            } else
                dataTable.setText(i, 3, null);
            if (value.get("creationDate") != null
                    && !value.get("creationDate").toString().equalsIgnoreCase("null"))
                dataTable.setText(i, 4, value.get("creationDate").isString().stringValue());
            if (value.get("updateDate") != null
                    && !value.get("updateDate").toString().equalsIgnoreCase("null"))
                dataTable.setText(i, 5, value.get("updateDate").isString().stringValue());
        }
    }

    /**
     * Create the dialog box for form.
     * 
     * @return the new dialog box
     */
    private PopupPanel createPopupPanel() {
        // Create a dialog box and set the caption text
        final PopupPanel popupPanel = new PopupPanel();
        popupPanel.setStyleName("redora-popups-Popup");
        HTML msg = new HTML("<center><b>Update Script Form</b></center>", false);

        FlexTable form = new FlexTable();
        form.setCellSpacing(6);

        final TextBox id = new TextBox();
        id.setReadOnly(true);
        form.setHTML(1, 0, "Id:");
        form.setWidget(1, 1, id);

        final TextBox scriptName = new TextBox();
        form.setHTML(2, 0, constants.redoraConfiguration_scriptName_form() + ":");
        form.setWidget(2, 1, scriptName);
        scriptName.setTitle("scriptName");
        scriptName.setReadOnly(true);

        final ListBox status = new ListBox();
        status.addItem(constants.redoraConfiguration_status_New_form(), "New");
        status.addItem(constants.redoraConfiguration_status_Ready_form(), "Ready");
        status.addItem(constants.redoraConfiguration_status_Error_form(), "Error");
        form.setHTML(3, 0, constants.redoraConfiguration_status_form() + ":");
        form.setWidget(3, 1, status);

        Set<Integer> set = scrollTable.getDataTable().getSelectedRows();
        Iterator<Integer> it = set.iterator();
        int row = it.next();
        id.setValue(scrollTable.getDataTable().getText(row, 0));
        scriptName.setValue(scrollTable.getDataTable().getText(row, 1));
        for (int i = 0; i < status.getItemCount(); i++) {
            if (status.getItemText(i).equalsIgnoreCase(scrollTable.getDataTable().getText(row, 2)))
                status.setSelectedIndex(i);
        }

        VerticalPanel dialogContents = new VerticalPanel();
        dialogContents.setSpacing(4);
        popupPanel.setWidget(dialogContents);

        dialogContents.add(msg);
        dialogContents.add(form);

        // Add a submit button at the bottom of the dialog
        Button submitButton = new Button("submit", new ClickHandler() {
            public void onClick(ClickEvent event) {
                String _url;
                _url = URL.encode(baseUpgradeUrl + "_operationType=updateRedoraScript&id="
                        + id.getValue() + "&scriptName=" + scriptName.getValue() + "&status="
                        + status.getItemText(status.getSelectedIndex()));
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, _url);
                builder.setCallback(new RequestCallback() {
                    public void onError(Request request, Throwable exception) {
                        Window.alert("Update Script failed!");
                    }

                    public void onResponseReceived(Request request, Response response) {
                        createDataList();
                    }
                });
                try {
                    builder.send();
                } catch (RequestException e) {
                    e.printStackTrace();
                }
                popupPanel.hide();
            }
        });

        // Add a close button at the bottom of the dialog
        Button closeButton = new Button("close", new ClickHandler() {
            public void onClick(ClickEvent event) {
                popupPanel.hide();
            }
        });

        HorizontalPanel panel = new HorizontalPanel();
        panel.add(submitButton);
        panel.add(closeButton);

        dialogContents.add(panel);

        // Return the dialog box
        return popupPanel;
    }
}
